---
title: 多模态
description: Spring AI 对话机器人多模态功能实现
sidebar_position: 3
---

# 多模态功能

多模态是指AI系统能够处理和理解多种类型的输入数据，如文本、图像、音频等。Spring AI 提供了多模态功能，让您的对话机器人不仅能理解文本，还能处理和分析图像等其他类型的数据。

## 多模态的应用场景

多模态功能在以下场景中特别有用：

1. **图像分析与描述** - 让机器人描述图片内容
2. **视觉问答** - 基于图片回答问题
3. **图像内容识别** - 识别图片中的物体、人物、文字等
4. **内容审核** - 检测图像中的不适当内容
5. **文档分析** - 理解包含图表和图像的文档

## 配置多模态支持

要使用Spring AI的多模态功能，首先需要配置支持多模态的模型提供商。目前，主要支持OpenAI的GPT-4 Vision等模型。

### 添加依赖

首先，确保添加了必要的依赖：

**Maven**:
```xml
<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-openai-spring-boot-starter</artifactId>
    <version>0.8.0</version>
</dependency>
```

**Gradle**:
```groovy
implementation 'org.springframework.ai:spring-ai-openai-spring-boot-starter:0.8.0'
```

### 配置多模态模型

在`application.properties`或`application.yml`中配置多模态模型：

```properties
spring.ai.openai.api-key=your-openai-api-key
spring.ai.openai.model=gpt-4-vision-preview
spring.ai.openai.max-tokens=300
```

## 实现图像处理功能

### 创建多模态服务

下面是一个处理图像的服务示例：

```java
package com.example.chatbot.service;

import org.springframework.ai.chat.ChatClient;
import org.springframework.ai.chat.ChatResponse;
import org.springframework.ai.chat.messages.Media;
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.chat.prompt.SystemPromptTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

@Service
public class MultimodalChatService {

    private final ChatClient chatClient;
    
    public MultimodalChatService(ChatClient chatClient) {
        this.chatClient = chatClient;
    }
    
    public String analyzeImage(MultipartFile image, String userQuestion) throws IOException {
        // 系统提示
        String systemPromptText = "你是一个能够分析图像的AI助手。请详细描述图像内容，并回答用户关于图像的问题。";
        SystemPromptTemplate systemPrompt = new SystemPromptTemplate(systemPromptText);
        
        // 创建包含图像的用户消息
        List<Media> mediaList = new ArrayList<>();
        mediaList.add(new Media(image.getContentType(), image.getBytes()));
        
        // 用户消息可以包含文本和媒体
        UserMessage userMessage = new UserMessage(userQuestion, mediaList);
        
        // 创建提示
        Prompt prompt = new Prompt(systemPrompt.getContents(), userMessage);
        
        // 获取响应
        ChatResponse response = chatClient.call(prompt);
        
        return response.getResult().getOutput().getContent();
    }
    
    public String analyzeImageUrl(String imageUrl, String userQuestion) {
        // 系统提示
        String systemPromptText = "你是一个能够分析图像的AI助手。请详细描述图像内容，并回答用户关于图像的问题。";
        SystemPromptTemplate systemPrompt = new SystemPromptTemplate(systemPromptText);
        
        // 创建包含图像URL的用户消息
        List<Media> mediaList = new ArrayList<>();
        mediaList.add(new Media(Media.MediaType.IMAGE, imageUrl));
        
        // 用户消息可以包含文本和媒体
        UserMessage userMessage = new UserMessage(userQuestion, mediaList);
        
        // 创建提示
        Prompt prompt = new Prompt(systemPrompt.getContents(), userMessage);
        
        // 获取响应
        ChatResponse response = chatClient.call(prompt);
        
        return response.getResult().getOutput().getContent();
    }
}
```

### 创建REST API

以下是处理图像上传和分析的控制器：

```java
package com.example.chatbot.controller;

import com.example.chatbot.service.MultimodalChatService;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;

@RestController
@RequestMapping("/api/chat/multimodal")
public class MultimodalController {

    private final MultimodalChatService multimodalChatService;
    
    public MultimodalController(MultimodalChatService multimodalChatService) {
        this.multimodalChatService = multimodalChatService;
    }
    
    @PostMapping(value = "/analyze-image", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public ImageAnalysisResponse analyzeImage(
            @RequestParam("image") MultipartFile image,
            @RequestParam("question") String question) throws IOException {
        
        String analysis = multimodalChatService.analyzeImage(image, question);
        return new ImageAnalysisResponse(analysis);
    }
    
    @PostMapping("/analyze-image-url")
    public ImageAnalysisResponse analyzeImageUrl(@RequestBody ImageUrlRequest request) {
        String analysis = multimodalChatService.analyzeImageUrl(request.getImageUrl(), request.getQuestion());
        return new ImageAnalysisResponse(analysis);
    }
    
    // 请求和响应的数据模型
    public static class ImageUrlRequest {
        private String imageUrl;
        private String question;
        
        // Getters and Setters
        public String getImageUrl() {
            return imageUrl;
        }
        
        public void setImageUrl(String imageUrl) {
            this.imageUrl = imageUrl;
        }
        
        public String getQuestion() {
            return question;
        }
        
        public void setQuestion(String question) {
            this.question = question;
        }
    }
    
    public static class ImageAnalysisResponse {
        private String analysis;
        
        public ImageAnalysisResponse(String analysis) {
            this.analysis = analysis;
        }
        
        // Getter
        public String getAnalysis() {
            return analysis;
        }
    }
}
```

## 高级多模态功能

### 图像与文本的混合处理

您可以创建更复杂的多模态体验，同时处理文本和图像：

```java
@Service
public class AdvancedMultimodalService {

    private final ChatClient chatClient;
    
    public AdvancedMultimodalService(ChatClient chatClient) {
        this.chatClient = chatClient;
    }
    
    public String processMultipleImages(List<MultipartFile> images, String userQuestion) throws IOException {
        // 系统提示
        String systemPromptText = "你是一个能够分析多张图像的AI助手。请比较这些图像，找出它们之间的关系，并回答用户的问题。";
        SystemPromptTemplate systemPrompt = new SystemPromptTemplate(systemPromptText);
        
        // 创建包含多张图像的用户消息
        List<Media> mediaList = new ArrayList<>();
        for (MultipartFile image : images) {
            mediaList.add(new Media(image.getContentType(), image.getBytes()));
        }
        
        // 用户消息
        UserMessage userMessage = new UserMessage(userQuestion, mediaList);
        
        // 创建提示
        Prompt prompt = new Prompt(systemPrompt.getContents(), userMessage);
        
        // 获取响应
        ChatResponse response = chatClient.call(prompt);
        
        return response.getResult().getOutput().getContent();
    }
    
    public String analyzeDocumentWithImages(MultipartFile document, List<MultipartFile> images, String userQuestion) throws IOException {
        // 实现文档和图像的混合分析...
        return "文档和图像分析结果";
    }
}
```

### 自定义图像处理指令

您可以通过自定义系统提示来指导模型如何处理图像：

```java
public String customImageAnalysis(MultipartFile image, String userQuestion, String analysisType) throws IOException {
    // 根据分析类型选择不同的系统提示
    String systemPromptText;
    
    switch (analysisType) {
        case "detailed":
            systemPromptText = "请提供图像的详细描述，包括所有可见的对象、人物、场景、颜色和细节。";
            break;
        case "summary":
            systemPromptText = "请简要总结图像的主要内容，只关注最重要的元素。";
            break;
        case "technical":
            systemPromptText = "请从技术角度分析图像，包括构图、光线、色彩平衡等摄影技术元素。";
            break;
        case "text-extraction":
            systemPromptText = "请提取并转录图像中的所有文本内容。";
            break;
        default:
            systemPromptText = "请分析图像并回答用户的问题。";
    }
    
    SystemPromptTemplate systemPrompt = new SystemPromptTemplate(systemPromptText);
    
    // 创建包含图像的用户消息
    List<Media> mediaList = new ArrayList<>();
    mediaList.add(new Media(image.getContentType(), image.getBytes()));
    
    UserMessage userMessage = new UserMessage(userQuestion, mediaList);
    
    // 创建提示
    Prompt prompt = new Prompt(systemPrompt.getContents(), userMessage);
    
    // 获取响应
    ChatResponse response = chatClient.call(prompt);
    
    return response.getResult().getOutput().getContent();
}
```

## 前端实现

以下是一个简单的前端实现，用于上传图像并获取分析结果：

```html
<!DOCTYPE html>
<html>
<head>
    <title>多模态对话机器人</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            max-width: 800px;
            margin: 0 auto;
            padding: 20px;
        }
        #preview {
            max-width: 100%;
            max-height: 300px;
            margin-top: 10px;
            display: none;
        }
        #result {
            margin-top: 20px;
            padding: 10px;
            border: 1px solid #ddd;
            border-radius: 5px;
            min-height: 100px;
            white-space: pre-wrap;
        }
        .form-group {
            margin-bottom: 15px;
        }
        label {
            display: block;
            margin-bottom: 5px;
        }
        button {
            padding: 8px 16px;
            background-color: #4caf50;
            color: white;
            border: none;
            cursor: pointer;
        }
        input[type="text"] {
            width: 100%;
            padding: 8px;
            box-sizing: border-box;
        }
    </style>
</head>
<body>
    <h1>Spring AI 多模态对话</h1>
    
    <div class="form-group">
        <label for="image-upload">上传图片:</label>
        <input type="file" id="image-upload" accept="image/*">
        <img id="preview" alt="图片预览">
    </div>
    
    <div class="form-group">
        <label for="question">问题或指令:</label>
        <input type="text" id="question" placeholder="请描述这张图片..." required>
    </div>
    
    <button id="analyze-btn">分析图片</button>
    
    <div>
        <h3>分析结果:</h3>
        <div id="result">结果将显示在这里...</div>
    </div>

    <script>
        document.getElementById('image-upload').addEventListener('change', function(e) {
            const preview = document.getElementById('preview');
            const file = e.target.files[0];
            
            if (file) {
                const reader = new FileReader();
                reader.onload = function(e) {
                    preview.src = e.target.result;
                    preview.style.display = 'block';
                }
                reader.readAsDataURL(file);
            }
        });
        
        document.getElementById('analyze-btn').addEventListener('click', async function() {
            const imageInput = document.getElementById('image-upload');
            const question = document.getElementById('question').value;
            const resultDiv = document.getElementById('result');
            
            if (!imageInput.files[0]) {
                alert('请先上传图片');
                return;
            }
            
            if (!question) {
                alert('请输入问题或指令');
                return;
            }
            
            resultDiv.textContent = '正在分析中...';
            
            const formData = new FormData();
            formData.append('image', imageInput.files[0]);
            formData.append('question', question);
            
            try {
                const response = await fetch('/api/chat/multimodal/analyze-image', {
                    method: 'POST',
                    body: formData
                });
                
                const data = await response.json();
                resultDiv.textContent = data.analysis;
            } catch (error) {
                console.error('Error:', error);
                resultDiv.textContent = '分析过程中发生错误，请稍后再试。';
            }
        });
    </script>
</body>
</html>
```

## 最佳实践

1. **优化图像大小** - 在发送到API之前压缩图像以提高性能
2. **提供清晰的指令** - 在提示中明确指定您希望模型如何分析图像
3. **结合上下文** - 将图像分析与对话上下文结合，以获得更连贯的体验
4. **处理多种格式** - 支持不同的图像格式（JPEG、PNG、GIF等）
5. **错误处理** - 实现适当的错误处理，以应对图像处理失败的情况

## 性能和成本考虑

多模态API通常比纯文本API更昂贵且处理时间更长。考虑以下优化：

1. **缓存常见结果** - 对于频繁使用的图像，缓存分析结果
2. **限制图像尺寸** - 将图像调整到合适的尺寸，避免发送不必要的大图像
3. **批量处理** - 如果可能，批量处理多个图像请求
4. **设置超时** - 为API调用设置适当的超时时间

## 下一步

了解了多模态功能后，您可以继续探索：

1. [提示词工程](../simulator/prompt-engineering)，优化对图像分析的提示
2. [向量模型](../chatpdf/vector-model)，将图像分析结果与文本信息结合

## 参考资料

- [Spring AI 官方文档 - 多模态功能](https://docs.spring.io/spring-ai/reference/)
- [OpenAI GPT-4 Vision API 文档](https://platform.openai.com/docs/guides/vision)
- [Spring AI GitHub 仓库](https://github.com/spring-projects/spring-ai) 